//var EXPORTED_SYMBOLS = ["sbiz.CleanSubject.prefPrefix"];

// Register namespaces
if (typeof sbiz == 'undefined')
{
    sbiz = new Array();
}
if (typeof sbiz.CleanSubject == 'undefined') 
{
    sbiz.CleanSubject = function(){
        // this is a stub only
        throw Components.results.NS_ERROR_ABORT;
    };
}

// Handy variables
sbiz.CleanSubject.prefs = null;
sbiz.CleanSubject.prefixes = null;
sbiz.CleanSubject.forward = null;
sbiz.CleanSubject.replyPrefix = null;
sbiz.CleanSubject.replyPostfix = null;
sbiz.CleanSubject.forwardPrefix = null;
sbiz.CleanSubject.forwardPostfix = null;
sbiz.CleanSubject.defaultReplyPrefix = "Re: ";
sbiz.CleanSubject.defaultReplyPostfix = "";
sbiz.CleanSubject.defaultForwardPrefix = "[Fwd: ";
sbiz.CleanSubject.defaultForwardPostfix = "]";
sbiz.CleanSubject.prefPrefixOld = 'extensions.cleansubject.';
sbiz.CleanSubject.prefPrefix = 'extensions.cleansubject@style-biz.de.';
sbiz.CleanSubject.prefStringPrefixes = 'prefixes';
sbiz.CleanSubject.prefStringForward = 'forward';
sbiz.CleanSubject.prefStringReplyPrefix = 'replyPrefix';
sbiz.CleanSubject.prefStringReplyPostfix = 'replyPostfix';
sbiz.CleanSubject.prefStringForwardPrefix = 'forwardPrefix';
sbiz.CleanSubject.prefStringForwardPostfix = 'forwardPostfix';
sbiz.CleanSubject.splitter = "|";

// The well known trim function
sbiz.CleanSubject.Trim = function(str)
{
    var result = "";
    if (str != result)
    {
        result = str.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); 
    }
    return result;
};

sbiz.CleanSubject.RemovePrefixes = function(str, prefixes)
{
    var position = 0;
           
    // while not having reached the end
    var noMoreMatch = false;
    while ((position < str.length) || !noMoreMatch)
    {
        noMoreMatch = true;
        
        // check each prefix
        for (var i = 0; i < prefixes.length; i++)
        {
            var prefix = prefixes[i];
            if (prefix != null)
            {
                try
                {
                    var searcher = new RegExp(prefix, "ig");
                    var search_result = str.search(searcher);
                    if (search_result == 0)
                    {
                        // Check for matches
                        var matches = searcher.exec(str);
                        // Matches length needs to be greater than 1, since the last
                        // match (e.g. array-index 1 -> length = 2) is the matched pattern.
                        if (matches && matches.length > 1)
                        {
                            // Complex regex - match ist the last array element
                            str = sbiz.CleanSubject.Trim(matches[matches.length - 1]);
                        }
                        else if (matches && matches.length == 1)
                        {
                            // Simple regex - get the difference of the match (first array element)
                            // and the subject
                            str = sbiz.CleanSubject.Trim(str.slice(matches[0].length));
                        }
                        else
                        {
                            // No real regex: Simple prefix matched
                            str = sbiz.CleanSubject.Trim(str.slice(prefix.length));
                        }
                        
                        // Store the prefix that lead to this match and set its count to 1
                        // If the prefix already exists, update its count.
                        if (sbiz.CleanSubject.lastMatchedPrefix == prefix)
                        {
                            sbiz.CleanSubject.lastMatchedPrefixCount++;
                        }
                        else
                        {
                            sbiz.CleanSubject.lastMatchedPrefix = prefix;
                            sbiz.CleanSubject.lastMatchedPrefixCount = 1;
                        }
                        
                        // If the count of the current active prefix exceeds the maximum count, 
                        // remove it (otherwise an endless loop will occur), e.g. with (.*)
                        if (sbiz.CleanSubject.lastMatchedPrefixCount > sbiz.CleanSubject.lastMatchedPrefixMaxCount)
                        {
                            sbiz.CleanSubject.prefixes[i] = null;
                        }
                        
                        position = 0;
                        noMoreMatch = false;
                        break;
                    }
                }
                catch(ex) {}
            }
        }
        position++;
    }

    return str;
}

// The well known array.contains function
sbiz.CleanSubject.ArrayContains = function(arr, elem)
{
    for (var i = 0; i < arr.length; i++) 
    {
        if (arr[i] == elem) 
        {
            return true;
        }
    }
    return false;
};

//Preference observer. Refills "gOneClickExtension.Preferences" after any changes in branch from "gOneClickExtension.prefPrefixString"
sbiz.CleanSubject.prefObserver =
{
    register: function()
    {
		var prefService = Components.classes["@mozilla.org/preferences-service;1"]
                                .getService(Components.interfaces.nsIPrefService);

        var branchName = sbiz.CleanSubject.prefPrefix.substr( 0, sbiz.CleanSubject.prefPrefix.length - 1 );

        dump(branchName + "\n");
    
		this._branch = prefService.getBranch(branchName);

		this._branch.QueryInterface(Components.interfaces.nsIPrefBranch2);

		this._branch.addObserver("", this, false);
        dump('CleanSubject registered preferences observer...\n');
	},

	unregister: function()
	{
		if( !this._branch ) return;
		this._branch.removeObserver("", this);
	},

	observe: function(aSubject, aTopic, aData)
	{
		if( aTopic != "nsPref:changed" ) return;

		sbiz.CleanSubject.SetVariablesFromPreferences();
        sbiz.CleanSubject.SetPrefixArrayFromPreferences();
        dump('CleanSubject updates from preferences...\n');
	}
}

sbiz.CleanSubject.SetPrefixArrayFromPreferences = function()
{
    //NOTE: Does sbiz.CleanSubject.prefs can be initialized only once?
    sbiz.CleanSubject.prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
    var _prefixes = sbiz.CleanSubject.Trim(
    sbiz.CleanSubject.prefs.getCharPref(
        sbiz.CleanSubject.prefPrefix + sbiz.CleanSubject.prefStringPrefixes));
    
    // Clean from multiple and trailing |
    _prefixes = _prefixes.replace(new RegExp("\\" + sbiz.CleanSubject.splitter + "+", "g"), sbiz.CleanSubject.splitter);
    _prefixes = _prefixes.replace(new RegExp("\\" + sbiz.CleanSubject.splitter + "+$", "g"), "");
    
    sbiz.CleanSubject.prefixes = _prefixes.split(sbiz.CleanSubject.splitter);
}

// Sets the "normal variables" (NOT the prefixes-array) from the settings
// in the preferences
sbiz.CleanSubject.SetVariablesFromPreferences = function()
{
    sbiz.CleanSubject.prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
    // Forwarding enabled?
    sbiz.CleanSubject.forward = sbiz.CleanSubject.prefs.getBoolPref(
        sbiz.CleanSubject.prefPrefix + sbiz.CleanSubject.prefStringForward);
    
    // Set reply and forward pre- and postfixes
    sbiz.CleanSubject.replyPrefix = sbiz.CleanSubject.prefs.getCharPref(
        sbiz.CleanSubject.prefPrefix + sbiz.CleanSubject.prefStringReplyPrefix);
    sbiz.CleanSubject.replyPostfix = sbiz.CleanSubject.prefs.getCharPref(
        sbiz.CleanSubject.prefPrefix + sbiz.CleanSubject.prefStringReplyPostfix);
    sbiz.CleanSubject.forwardPrefix = sbiz.CleanSubject.prefs.getCharPref(
        sbiz.CleanSubject.prefPrefix + sbiz.CleanSubject.prefStringForwardPrefix);
    sbiz.CleanSubject.forwardPostfix = sbiz.CleanSubject.prefs.getCharPref(
        sbiz.CleanSubject.prefPrefix + sbiz.CleanSubject.prefStringForwardPostfix);
}

// Register preference observer
window.addEventListener("load", sbiz.CleanSubject.prefObserver.register, true);

// Unregister preference observer
window.addEventListener("unload", sbiz.CleanSubject.prefObserver.unregister, true);